package com.restaurant.application.service.feigh;

import com.google.common.base.Charsets;
import com.google.common.base.MoreObjects;
import com.google.common.hash.Hashing;
import com.google.common.io.BaseEncoding;
import com.nebutown.boxes.txboxes.Json;
import feign.Feign;
import feign.jackson.JacksonDecoder;
import feign.jackson.JacksonEncoder;

import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

public class Gateway2dfires {

    public static enum EOrderState {

        Normal("1", "正常状态"),
        Merge("2", "并单状态"),
        Dispose("3", "撤消状态"),
        Payed("4", "结账状态"),
        Timeout("5", "超时状态"),
        ;


        private final String mId;
        private final String mDesc;

        EOrderState(String id, String desc) {

            this.mId = id;
            this.mDesc = desc;
        }

        public String getDesc() {
            return mDesc;
        }

        public String getId() {
            return mId;
        }
    }

    static final String APP_KEY = "0e3a2f353f074b0c1fb82b55de9e2c95";
    static final String APP_SECRET = "1b3cc4e99ae18eeced309628b30669ba";

    private static final IGateway2dfire I_GATEWAY_2_DFIRE = build0();

    private static IGateway2dfire build0() {

        Feign.Builder builder =
                Feign.builder()
                        .decoder(new JacksonDecoder())
                        .encoder(new JacksonEncoder());

        return builder.target(IGateway2dfire.class, "http://gateway.2dfire.com");
    }


    /**
     * must specify entityId, other params may be null.
     *
     * @param entityId
     * @param currDate,    such as: "20190729"
     * @param pageIndex
     * @param pageSize
     * @param eOrderStates
     * @return
     */
    public static IGateway2dfire.TResponse getOrderList(String entityId, String currDate, Integer pageIndex, Integer pageSize, EOrderState... eOrderStates) {


        List<String> orderStatusList = eOrderStates.length == 0
                ? Arrays.asList("1", "2", "3", "4", "5")
                : Arrays.stream(eOrderStates).map(EOrderState::getId).collect(Collectors.toList());


        TreeMap<String, Object> params = getCommonParams("com.dfire.open.shop.order.query");


        params.put("orderStatusList", Json.toJson(orderStatusList));


        params.put("entityId", entityId);
        params.put("currDate", MoreObjects.firstNonNull(currDate, getCurDateFormat("yyyyMMdd")));
        params.put("pageIndex", MoreObjects.firstNonNull(pageIndex, (int) 1));
        params.put("pageSize", MoreObjects.firstNonNull(pageSize, (int) 50));

        params.put("sign", uHex(sha1(orderAscAndConcat(params))));
        return I_GATEWAY_2_DFIRE.queryOrders(params);

    }

    public static String getCurDateFormat(String format) {

        LocalDate localDate = LocalDate.now(ZoneId.of("Asia/Shanghai"));
        return localDate.format(DateTimeFormatter.ofPattern(format));
    }


    public static IGateway2dfire.TOrderDetailResponse getOrderDetail(String entityId, String... orderIds) {

        if (orderIds.length == 0) throw new IllegalArgumentException("Must specify orderid");

        TreeMap<String, Object> params = getCommonParams("com.dfire.open.order.instance.query");


        params.put("entityId", entityId);
        params.put("orderIds", Json.toJson(orderIds));

        params.put("sign", uHex(sha1(orderAscAndConcat(params))));
        return I_GATEWAY_2_DFIRE.queryOrderDetail(params);
    }

    private static String orderAscAndConcat(Map<String, Object> params) {

        final String reduce = params.entrySet().stream().map(entry -> entry.getKey() + entry.getValue().toString()).reduce("", (s1, s2) -> s1 + s2);
        return
                APP_SECRET + reduce + APP_SECRET;
    }

    static TreeMap<String, Object> getCommonParams(String methodType) {


        return new TreeMap<String, Object>() {

            {
                put("appKey", APP_KEY);
                put("v", 1.0f);
                put("method", methodType);
                put("timestamp", System.currentTimeMillis());
                put("format", "json");
                put("locale", "zh_CN");
                put("lang", "zh_CN");
                put("env", "publish");


            }
        };
    }


    public static byte[] sha1(String string) {


        return Hashing.sha1().hashString(string, Charsets.UTF_8).asBytes();
    }

    public static String uHex(byte[] bytes) {

        return BaseEncoding.base16().encode(bytes).toUpperCase();
    }

}
